﻿using System;
using LinqToExcel;
using MFilesAPI;

namespace FSAG.UserImporter
{
    /// <summary>
    /// Class ExcelQueryInitializer contains the necessary mappings and transformations for the excel to object mapping
    /// </summary>
    public static class ExcelQueryInitializer
    {
        /// <summary>
        /// Holds an ExcelQueryFactor instance for all user belongings
        /// </summary>
        public static ExcelQueryFactory User { get; set; }

        /// <summary>
        /// Holds an ExcelQueryFactor instance for all group belongings
        /// </summary>
        public static ExcelQueryFactory Group { get; set; }

        private static string Path { get; set; }

        /// <summary>
        /// Used to initialize the ExcelQueryInitializer with a given path
        /// </summary>
        /// <param name="path">Location of the excel file with the group resp. user list</param>
        public static void Initialize(string path)
        {
            Path = path;
            User = new ExcelQueryFactory(Path);
            Group = new ExcelQueryFactory(Path);
            InitializeMappings();
            InitializeTransformations();
        }

        /// <summary>
        /// Method used for the initialisation of all mappings 
        /// </summary>
        private static void InitializeMappings()
        {
            User.AddMapping<User>(account => account.Modified, ConfigManager.GetSetting("ColumnUserModified"));
            User.AddMapping<User>(account => account.UserName, ConfigManager.GetSetting("ColumnUserName"));
            User.AddMapping<User>(account => account.FirstName, ConfigManager.GetSetting("ColumnUserFirstName"));
            User.AddMapping<User>(account => account.LastName, ConfigManager.GetSetting("ColumnUserLastName"));
            User.AddMapping<User>(account => account.FullName, ConfigManager.GetSetting("ColumnUserFullName"));
            User.AddMapping<User>(account => account.Mail, ConfigManager.GetSetting("ColumnUserMail"));
            User.AddMapping<User>(account => account.LicenseType, ConfigManager.GetSetting("ColumnUserLicenseType"));
            User.AddMapping<User>(account => account.State, ConfigManager.GetSetting("ColumnUserStatus"));
            User.AddMapping<User>(account => account.MFilesPassword, ConfigManager.GetSetting("ColumnUserPassword"));
            User.AddMapping<User>(account => account.UserGroup1, ConfigManager.GetSetting("ColumnUserGroup1"));
            User.AddMapping<User>(account => account.UserGroup2, ConfigManager.GetSetting("ColumnUserGroup2"));
            User.AddMapping<User>(account => account.UserGroup3, ConfigManager.GetSetting("ColumnUserGroup3"));

            User.AddMapping<User>(account => account.MFUserAccountVaultRoleFullControl, ConfigManager.GetSetting("ColumnUserFullControl"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleSeeAllObjects, ConfigManager.GetSetting("ColumnUserSeeAllObjects"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleUndeleteObjects, ConfigManager.GetSetting("ColumnUserUndeleteObjects"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleDestroyObjects, ConfigManager.GetSetting("ColumnUserDestroyObjects"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleForceUndoCheckout, ConfigManager.GetSetting("ColumnUserForceUndoCheckout"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleChangeObjectSecurity, ConfigManager.GetSetting("ColumnUserChangeObjectSecurity"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleChangeMetadataStructure, ConfigManager.GetSetting("ColumnUserChangeMetadataStructure"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleManageUserAccounts, ConfigManager.GetSetting("ColumnUserManageUserAccounts"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleManageCommonViews, ConfigManager.GetSetting("ColumnUserManageCommonViews"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleCreateObjects, ConfigManager.GetSetting("ColumnUserCreateObjects"));
            User.AddMapping<User>(account => account.MFUserAccountVaultRoleManageTraditionalFolders, ConfigManager.GetSetting("ColumnUserManageTraditionalFolders"));
            User.AddMapping<User>(account => account.Language, ConfigManager.GetSetting("ColumnUserLanguage"));
            User.AddMapping<User>(account => account.AccountID, ConfigManager.GetSetting("ColumnUserAccountID"));

            Group.AddMapping<Group>(group => group.GroupStatus, ConfigManager.GetSetting("ColumnGroupStatus"));
            Group.AddMapping<Group>(group => group.GroupID, ConfigManager.GetSetting("ColumnGroupID"));
            Group.AddMapping<Group>(group => group.Modified, ConfigManager.GetSetting("ColumnGroupModified"));
            Group.AddMapping<Group>(group => group.GroupName, ConfigManager.GetSetting("ColumnGroupName"));
        }

        /// <summary>
        /// Method used for initializing all transformations 
        /// </summary>
        private static void InitializeTransformations()
        {
            User.AddTransformation<User>(user => user.LicenseType, ConvertLicenseType);
            User.AddTransformation<User>(user => user.State, ConvertStatus);
            Group.AddTransformation<Group>(group => group.GroupStatus, ConvertStatus);

            User.AddTransformation<User>(user => user.Language, SetLanguage);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleFullControl, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleFullControl : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleSeeAllObjects, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleSeeAllObjects : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleUndeleteObjects, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleUndeleteObjects : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleDestroyObjects, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleDestroyObjects : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleForceUndoCheckout, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleForceUndoCheckout : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleChangeObjectSecurity, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleChangeObjectSecurity : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleChangeMetadataStructure, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleChangeMetadataStructure : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleManageUserAccounts, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleManageUserAccounts : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleManageCommonViews, property => property == "Ja" ? (object)MFUserAccountVaultRole.MFUserAccountVaultRoleManageCommonViews : null);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleCreateObjects, property => property == "Nein" ? null : (object)MFUserAccountVaultRole.MFUserAccountVaultRoleCreateObjects);
            User.AddTransformation<User>(user => user.MFUserAccountVaultRoleManageTraditionalFolders, property => property == "Nein" ? null : (object)MFUserAccountVaultRole.MFUserAccountVaultRoleManageTraditionalFolders);
            User.AddTransformation<User>(user => user.MFilesPassword, password => password ?? string.Empty);
        }

        /// <summary>
        /// Map an ordinal number to a given language
        /// </summary>
        /// <param name="language">The language name</param>
        /// <returns>Returns the mfiles language code</returns>
        private static object SetLanguage(string language)
        {
            switch (language)
            {
                case "Französisch":
                    return 101;
                default:
                    return 0;
            }
        }

        /// <summary>
        /// Converts a given string status to the related enum status
        /// </summary>
        /// <param name="value">String representation of the status</param>
        /// <returns>Returns the corresponding enum state</returns>
        private static Object ConvertStatus(string value)
        {
            switch (value)
            {
                case "Deaktiv":
                    return State.Deactiv;

                case "Gelöscht":
                    return State.Deleted;
                default:
                    return State.Activ;
            }
        }

        /// <summary>
        /// Converts a given string license type to the related enum License type
        /// </summary>
        /// <param name="licenseType">String representation of the license type</param>
        /// <returns>Returns the corresponding enum license type</returns>
        private static object ConvertLicenseType(string licenseType)
        {
            switch (licenseType)
            {
                case "Einzelbenutzerlizenz":
                    return MFLicenseType.MFLicenseTypeNamedUserLicense;

                case "Keine Lizenz":
                    return MFLicenseType.MFLicenseTypeNone;

                case "Mehrbenutzerlizenz":
                    return MFLicenseType.MFLicenseTypeConcurrentUserLicense;

                case "Nur-Lesen-Lizenz":
                    return MFLicenseType.MFLicenseTypeReadOnlyLicense;
            }
            return null;
        }
    }
}
